#include "MACD_chart.h"
#include <map>
#include "mouse_pos.h"
#include <cfloat>
#include <iostream>
#include <algorithm>

static std::vector<StockData> MACDData;
// 日期对应的下标
static std::map<std::string,size_t> dateRangeMap;
// 起止时间:
std::string currentStartDate,currentEndDate;
// 绘制范围
std::vector<StockData> g_currentDrawRangeData;
// 用于绘制的最大值最小值
float g_max_y_value = 0, g_min_y_value = 0;
// 数值范围:
float g_y_value_range = 0;
// 120日价格平均值比例
std::vector<double> g_vector_price_ma120_level;
// 60日价格平均值比例
std::vector<double> g_vector_price_ma60_level;
// 30日价格平均值比例
std::vector<double> g_vector_price_ma30_level;
// 120日MACD平均值水平
std::vector<double> g_vector_macd_ma120_level;
// 60日MACD平均值水平
std::vector<double> g_vector_macd_ma60_level;
// 30日MACD平均值水平
std::vector<double> g_vector_macd_ma30_level;
// 截取数据的起始位置
size_t g_start_index = 0;



// 获取指定日期在数据中的索引
int getDateIndex(const std::string& date) {
    auto it_end = dateRangeMap.lower_bound(date);
    if(dateRangeMap.end()==it_end)
    {
        return dateRangeMap.size()-1;
    }
    if(dateRangeMap.begin() == it_end)
    {
        return it_end->second;// 怕是有些股票还没上市, 还没到开始的时候.
    }
    if(!dateRangeMap.contains(date))
    {
        --it_end;
    }
    if(dateRangeMap.end()==it_end)
    {
        return 0;
    }
    size_t endIndex = it_end->second;
    return endIndex; 
}

// 生成新的MACD数据

// 计算指数移动平均线 (EMA)
std::vector<double> calculateEMA(const std::vector<double> &prices,int period) {
    std::vector<double> ema(prices.size(), 0.0);
    double multiplier = 2.0 / (period + 1);
    ema[period - 1] = 0.0;
    for (int i = 0; i < period; ++i) {
        ema[period - 1] += prices[i];
    }
    ema[period - 1] /= period;

    for (int i = period; i < prices.size(); ++i) {
        ema[i] = (prices[i] - ema[i - 1]) * multiplier + ema[i - 1];
    }
    return ema;
}

// 计算MACD
void calculateMACD(int shortPeriod = 6, int longPeriod = 13, int signalPeriod = 5) {
    std::vector<double> prices(MACDData.size(), 0.0) ;
    for (int i = 0; i < MACDData.size(); ++i) {
        prices[i] = MACDData[i].close;
    }
    std::vector<double> shortEMA = calculateEMA(prices,shortPeriod);
    std::vector<double> longEMA = calculateEMA(prices,longPeriod);
    std::vector<double> macdLine(prices.size(), 0.0);
    std::vector<double> signalLine(prices.size(), 0.0);     
    std::vector<double> histogram(prices.size(), 0.0);

    for (int i = longPeriod - 1; i < prices.size(); ++i) {
        macdLine[i] = shortEMA[i] - longEMA[i];
    }

    signalLine = calculateEMA(macdLine, signalPeriod);

    for (int i = longPeriod + signalPeriod - 2; i < prices.size(); ++i) {
        histogram[i] = macdLine[i] - signalLine[i];
    }

    for(int i=0;i<MACDData.size();i++)
    {
        MACDData[i].macd = macdLine[i];
        MACDData[i].macd_signal = signalLine[i];
        MACDData[i].macd_histogram = histogram[i];
    }

    //return histogram;
}

struct priceMALevel {
    double maxPrice;
    double minPrice;
    double ma;
    double level;
};

// 内部调用:计算价格平均值
priceMALevel calculatePriceMA(size_t index,size_t period,const double max_value,const double min_value)
{
    priceMALevel _result;
    if(0==max_value){_result.maxPrice = -9e9;}    else{_result.maxPrice = max_value;}
    if(0==min_value){_result.minPrice = 9e9;}    else{_result.minPrice = min_value;}
    double _total = 0;
    for(size_t i=index;i>0&&i>index-period;--i)
    {
        const double &price = MACDData[i].close;
        if(0==max_value)
        {
            if(price<_result.minPrice)
            {
                _result.minPrice=price;
            }
            if(price>_result.maxPrice)
            {
                _result.maxPrice=price;
            }
        }
        _total+=price;
    }// END for
    
    _result.ma = _total/period;
    _result.level = (_result.ma-_result.minPrice)/(_result.maxPrice-_result.minPrice);
    return _result;
}
struct priceMACDLevel {
    double maxMACD;
    double minMACD;
    double ma;
    double level;
};
// 内部调用:计算价格平均值
priceMACDLevel calculateMACDMA(size_t index,size_t period,const double max_value,const double min_value)
{
    priceMACDLevel _result;
    if(0==max_value){_result.maxMACD = -9e9;}  else{_result.maxMACD=max_value;}
    if(0==min_value){_result.minMACD = 9e9;}    else{_result.minMACD=min_value;}
    double _total = 0;
    for(size_t i=index;i>0&&i>index-period;--i)
    {
        const double &macd = MACDData[i].macd;
        if(0==max_value)
        {
            if(macd<_result.minMACD)
            {
                _result.minMACD=macd;
            }
            if(macd>_result.maxMACD)
            {
                _result.maxMACD=macd;
            }
        }
        _total+=macd;
    }// END for
    
    _result.ma = _total/period;
    double _calc_1 = _result.ma-_result.minMACD;
    double _calc_2 = _result.maxMACD-_result.minMACD;
    // std::cout<<"#178 _calc:"<< _calc_1 <<" / "<< _calc_2
    //     <<"\t_result.maxMACD="<<_result.maxMACD<<"\t_result.minMACD="<<_result.minMACD 
    //     <<"\tmax_value="<<max_value<<"\tmin_value="<<min_value
    //     <<std::endl;
    _result.level = (_calc_1)/(_calc_2);
    return _result;
}

// 计算背离相关的价格水平与MACD水平
// 必须在算完MACD后再算这个
void calculateMACDLevelAndPriceLevel() {
    g_vector_price_ma120_level = std::vector(MACDData.size(),0.0);
    g_vector_price_ma60_level = std::vector(MACDData.size(),0.0);
    g_vector_price_ma30_level = std::vector(MACDData.size(),0.0);
    g_vector_macd_ma120_level = std::vector(MACDData.size(),0.0);
    g_vector_macd_ma60_level = std::vector(MACDData.size(),0.0);
    g_vector_macd_ma30_level = std::vector(MACDData.size(),0.0);
    for (size_t i = 120; i < MACDData.size(); ++i) {
        priceMALevel price_ma120 = calculatePriceMA(i,120,0,0);
        g_vector_price_ma120_level[i] = price_ma120.level;
        priceMALevel price_ma60 = calculatePriceMA(i,60,price_ma120.maxPrice,price_ma120.minPrice);
        g_vector_price_ma60_level[i] = price_ma60.level;
        priceMALevel price_ma30 = calculatePriceMA(i,30,price_ma120.maxPrice,price_ma120.minPrice);
        g_vector_price_ma30_level[i] = price_ma30.level;
        // MACD:        
        priceMACDLevel macd_ma120 = calculateMACDMA(i,120,0,0);
        g_vector_macd_ma120_level[i] = macd_ma120.level;
        priceMACDLevel macd_ma60 = calculateMACDMA(i,60,macd_ma120.maxMACD,macd_ma120.minMACD);
        g_vector_macd_ma60_level[i] = macd_ma60.level;
        priceMACDLevel macd_ma30 = calculateMACDMA(i,30,macd_ma120.maxMACD,macd_ma120.minMACD);
        g_vector_macd_ma30_level[i] = macd_ma30.level;
        // std::cout<<"MACD max:"<< macd_ma120.maxMACD<<"\tmin:"<<macd_ma120.minMACD 
        //     <<"\tma30:"<< macd_ma30.ma<<"\t30level:"<<g_vector_macd_ma30_level[i] <<std::endl;
    }// END for
}


// 设置一只股票的所有数据    
void setMACDData(const std::vector<StockData>& data)
{
    MACDData = data;
    calculateMACD();
    dateRangeMap.clear();
    // 下标的查表依据:
    for(size_t i=0;i<MACDData.size();i++)
    {
        dateRangeMap[MACDData[i].trade_date] = i;
    }
    // 计算价格水平与MACD水平
    calculateMACDLevelAndPriceLevel();
}

// 设置日期范围
void setDateRangeMACD(const std::string& startDate, const std::string& endDate)
{
    currentStartDate = startDate;
    currentEndDate = endDate;

    // 计算绘制所需的数据: 金叉,  卖出点,  买入点
    // 下标:
    size_t EndIndex = getDateIndex(endDate);
    size_t StartIndex = EndIndex>=90?EndIndex-90+1:0;
    g_start_index = StartIndex;
    g_currentDrawRangeData.clear();
    // g_currentDrawRangeData的内容为: 从startDate到endDate的MACD数据
    for(size_t i=StartIndex;i<=EndIndex;i++)
    {
        g_currentDrawRangeData.push_back(MACDData[i]);
    }
    // 如果数组的数量大于90, 则裁到90
    if(g_currentDrawRangeData.size()>90)
    {
        g_currentDrawRangeData.erase(g_currentDrawRangeData.begin(),g_currentDrawRangeData.begin()+g_currentDrawRangeData.size()-90);
    }

    // 取Y轴的最大值最小值:
    g_max_y_value = FLT_MIN;
    g_min_y_value = FLT_MAX;
    for(size_t i=0;i<g_currentDrawRangeData.size();i++)
    {
        if(g_currentDrawRangeData[i].macd>g_max_y_value)
        {
            g_max_y_value = g_currentDrawRangeData[i].macd;
        }
        else if(g_currentDrawRangeData[i].macd<g_min_y_value)
        {
            g_min_y_value = g_currentDrawRangeData[i].macd;
        }

        if(g_currentDrawRangeData[i].macd_signal>g_max_y_value)
        {
            g_max_y_value = g_currentDrawRangeData[i].macd;
        }
        else if(g_currentDrawRangeData[i].macd_signal<g_min_y_value)
        {
            g_min_y_value = g_currentDrawRangeData[i].macd;
        }

        if(g_currentDrawRangeData[i].macd_histogram>g_max_y_value)
        {
            g_max_y_value = g_currentDrawRangeData[i].macd;
        }
        else if(g_currentDrawRangeData[i].macd_histogram<g_min_y_value)
        {
            g_min_y_value = g_currentDrawRangeData[i].macd;
        }

    }

    g_y_value_range = std::max(abs(g_max_y_value),abs(g_min_y_value))*1.05;
}

// 绘制MACDonald图表
void drawMACDChart(ImDrawList* drawList, ImVec2 pos, ImVec2 size)
{
    // 中线:
    drawList->AddLine(ImVec2(pos.x,pos.y+size.y/2),ImVec2(pos.x+size.x,pos.y+size.y/2),ImColor(100,100,100),1);

    for(size_t i=1;i<g_currentDrawRangeData.size();i++ )
    {
        float step_weight = size.x/g_currentDrawRangeData.size();

        float _pos_x_1 = pos.x+step_weight*(i-1);
        float _pos_x_2 = pos.x+step_weight*(i);

        // 用StockData的macd来画线
        float last_macd = g_currentDrawRangeData[i-1].macd;
        float macd = g_currentDrawRangeData[i].macd;
        float macd_pos_y_1 = pos.y+size.y/2-(last_macd/g_y_value_range)*size.y/2;
        float macd_pos_y_2 = pos.y+size.y/2-(macd/g_y_value_range)*size.y/2;
        drawList->AddLine(ImVec2(_pos_x_1,macd_pos_y_1),ImVec2(_pos_x_2,macd_pos_y_2),ImColor(0, 255, 255),1);
        
        float last_macd_signal = g_currentDrawRangeData[i-1].macd_signal;
        float macd_signal = g_currentDrawRangeData[i].macd_signal;
        float macd_signal_pos_y_1 = pos.y+size.y/2 - (last_macd_signal/g_y_value_range)*size.y/2;
        float macd_signal_pos_x_2 = pos.y+size.y/2 - (macd_signal/g_y_value_range)*size.y/2;
        drawList->AddLine(ImVec2(_pos_x_1,macd_signal_pos_y_1),ImVec2(_pos_x_2,macd_signal_pos_x_2),ImColor(255, 0, 0),1);

        float macd_histogram = g_currentDrawRangeData[i].macd_histogram;
        float macd_histogram_pos_y_1 = pos.y+size.y/2 - (macd_histogram/g_y_value_range)*size.y/2;
        float macd_histogram_pos_y_2 = pos.y+size.y/2;
        ImColor histogram_color = ImColor(255, 0, 0);
        if(macd_histogram<0)
        {
            histogram_color = ImColor(0, 255, 0);
        }
        drawList->AddLine(ImVec2(_pos_x_2,macd_histogram_pos_y_1),ImVec2(_pos_x_2,macd_histogram_pos_y_2),histogram_color,1);

        // BEGIN 背离信息:
        const double &macd_120_level= g_vector_macd_ma120_level[g_start_index+i];
        const double &macd_60_level = g_vector_macd_ma60_level[g_start_index+i];
        const double &macd_30_level = g_vector_macd_ma30_level[g_start_index+i];
        const double &macd_120_last_level = g_vector_macd_ma120_level[g_start_index+i-1];
        const double &macd_60_last_level = g_vector_macd_ma60_level[g_start_index+i-1];
        const double &macd_30_last_level = g_vector_macd_ma30_level[g_start_index+i-1];
        const double &price_120_level = g_vector_price_ma120_level[g_start_index+i];
        const double &price_60_level = g_vector_price_ma60_level[g_start_index+i];
        const double &price_30_level = g_vector_price_ma30_level[g_start_index+i];
        const double &price_120_last_level = g_vector_price_ma120_level[g_start_index+i-1];
        const double &price_60_last_level = g_vector_price_ma60_level[g_start_index+i-1];
        const double &price_30_last_level = g_vector_price_ma30_level[g_start_index+i-1];

        // double macd_120_level_y_1 = pos.y+size.y/2 - macd_120_last_level*size.y/2;
        // double macd_120_level_y_2 = pos.y+size.y/2 - macd_120_level*size.y/2;
        // drawList->AddLine(ImVec2(_pos_x_1,macd_120_level_y_1),ImVec2(_pos_x_2,macd_120_level_y_2),ImColor(100, 100, 0),1);
        // double macd_60_level_y_1  = pos.y+size.y/2 - macd_60_last_level *size.y/2;
        // double macd_60_level_y_2  = pos.y+size.y/2 - macd_60_level *size.y/2;
        // drawList->AddLine(ImVec2(_pos_x_1,macd_60_level_y_1),ImVec2(_pos_x_2,macd_60_level_y_2),ImColor(150, 150, 0),1);
        double macd_30_level_y_1  = pos.y+size.y - macd_30_last_level *size.y/2;
        double macd_30_level_y_2  = pos.y+size.y - macd_30_level *size.y/2;
        drawList->AddLine(ImVec2(_pos_x_1,macd_30_level_y_1),ImVec2(_pos_x_2,macd_30_level_y_2),ImColor(200, 200, 1),0);

        // double price_120_level_y_1 = pos.y+size.y/2 - price_120_last_level*size.y/2;
        // double price_120_level_y_2 = pos.y+size.y/2 - price_120_level*size.y/2;
        // drawList->AddLine(ImVec2(_pos_x_1,price_120_level_y_1),ImVec2(_pos_x_2,price_120_level_y_2),ImColor(100, 0, 100),1);
        // double price_60_level_y_1  = pos.y+size.y/2 - price_60_last_level *size.y/2;
        // double price_60_level_y_2  = pos.y+size.y/2 - price_60_level *size.y/2;
        // drawList->AddLine(ImVec2(_pos_x_1,price_60_level_y_1),ImVec2(_pos_x_2,price_60_level_y_2),ImColor(150, 0, 150),1);
        double price_30_level_y_1  = pos.y+size.y - price_30_last_level *size.y/2;
        double price_30_level_y_2  = pos.y+size.y - price_30_level *size.y/2;
        drawList->AddLine(ImVec2(_pos_x_1,price_30_level_y_1),ImVec2(_pos_x_2,price_30_level_y_2),ImColor(200, 0, 200),1);
        
        // END 背离信息
    }// END for
    
    // 鼠标坐标:
    int mousePosX = getMousePosX();
    int mousePosY = getMousePosY();
    drawList->AddLine(ImVec2(mousePosX-9990, mousePosY), ImVec2(mousePosX+9990, mousePosY), ImColor(111, 111, 111));
    drawList->AddLine(ImVec2(mousePosX,mousePosY -9999), ImVec2(mousePosX,mousePosY +9999), ImColor(111, 111, 111));
}
